package com.ids.enigha;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

public class MyLocation implements LocationListener{
	Location location;
	static LocationManager locationManager;
	Context trackingService; 
	private String GPS_location = null;
	public static final String ACTION_LOCATION_FETCHED = "com.hangover.tracker.LOCATON_FETCHED";
	public static String latitude = "";
	public static String longitude = "";
	public static String accval = "";
	
	int batterylevel;
	DatabaseHelper dbh;
	Cursor cursor;
	public boolean pendingService = false;
	
	public static String URL_PATH = "http://192.237.167.247:9090/eNigha-trackingserver-1.0-SNAPSHOT/devices";
	
	
	public MyLocation(Context trackingService)
	{
		this.trackingService = trackingService;
		locationManager = (LocationManager)trackingService.getSystemService(
				Context.LOCATION_SERVICE);
	}
	public MyLocation()
	{
		
	}
	public String getBestProvider()
	{
		Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setSpeedRequired(false);
        criteria.setCostAllowed(true); 
		String provider = locationManager.getBestProvider(criteria, true);
		return provider;
	}
	public void requestLocUpdates(String provider)
	{
		locationManager.requestLocationUpdates(provider, 10000, 0, this);
		if(locationManager != null)
			location = locationManager.getLastKnownLocation(provider);
		if(location != null)
		{
			latitude = ""+location.getLatitude();
			longitude = ""+location.getLongitude();
			accval = location.getAccuracy()+"";
			new SendDataToServer().execute();
		}
	}
	public Location getCurrloc()
	{
		return location;
	}
	public void getCurrentLocation()
	{	
		if(isInternetPresent(trackingService) && isNetworkEnabled())
		{
			requestLocUpdates(LocationManager.NETWORK_PROVIDER);		
		}
		else if(isGPSEnabled())
		{
			System.out.println("raj Fetching location using : "+getBestProvider());
			if(getBestProvider() != null)
				requestLocUpdates(getBestProvider());
			else
				requestLocUpdates(LocationManager.GPS_PROVIDER);
		} 
		else if(isNetworkEnabled())
		{
			System.out.println("raj Fetching location using: "+LocationManager.NETWORK_PROVIDER);
			requestLocUpdates(LocationManager.NETWORK_PROVIDER);						
		}
	}
	
	public static boolean isGPSEnabled()
    {
        boolean enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        return enabled;
    }
	public boolean isNetworkEnabled()
    {    	
        boolean enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        return enabled;// && isInternetPresent(trackingService);
    }
	
	public void removeUpdates()
	{
		locationManager.removeUpdates(this);
		System.out.println("raj locationManager.removeUpdates(this);");
	}
	public boolean isInternetPresent(Context context){
        ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
          if (connectivity != null)
          {
              NetworkInfo[] info = connectivity.getAllNetworkInfo();
              if (info != null)
                  for (int i = 0; i < info.length; i++)
                      if (info[i].getState() == NetworkInfo.State.CONNECTED)
                      {
                          return true;
                      }
 
          }
          return false;
    }

	public boolean isInternetEnabledForcely(Context context)
	{
		SharedPreferences prefs = context.getSharedPreferences("KEY_DETAILS", context.MODE_PRIVATE);
		System.out.println("raj saved time: "+prefs.getBoolean("isServiceRunning", false));
		return prefs.getBoolean("isInternetEnabledForcely", false);
	}
	public void setMobileDataEnabled(boolean enable, Context context)
    {
    	try
    	{	   
    		ConnectivityManager dataManager;
	    	dataManager  = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
	    	Method dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
	    	dataMtd.setAccessible(true);
	    	dataMtd.invoke(dataManager, enable);
    	}
    	catch(Exception ex)
    	{
    		System.out.println("raj Error in enabling the MObile Data: "+ex);
    	}	    	 
    }

	@Override
	public void onLocationChanged(Location loc) {
		// TODO Auto-generated method stub	\
		location = loc;
		double lat = loc.getLatitude();
        double lng = loc.getLongitude();  
        
        accval = loc.getAccuracy()+"";
        
        latitude = ""+lat;
        longitude = ""+lng;
        
        new SendDataToServer().execute();
               
        String loct = "Latitude: "+latitude+" Longitude: "+longitude;
        String current_location = latitude+","+longitude;
        
        System.out.println("raj location: "+current_location);
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
		System.out.println("raj onStatusChanged: "+provider);
	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
		System.out.println("raj onProviderEnabled: "+provider);
		
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
		System.out.println("raj onProviderDisabled: "+provider);
		if(provider.equals(LocationManager.NETWORK_PROVIDER))
		{
			removeUpdates();
			requestLocUpdates(getBestProvider());
		}			
	}
	
	public class SendDataToServer extends AsyncTask<Void, Integer, Integer>
	{
		protected Integer doInBackground(Void... params) {
			
			HttpResponse response = null;
			DefaultHttpClient httpclient = null;
			HttpPut httpost = null;
			int responseCode = 0;
			
			String devid = getDeviceID();

			String paramFormatStr = "{latitude:\"%s\",longitude:\"%s\",timestamp:\"%s\",info:{info:\"{BATTERY:\'%s\',ACCURACY:\'%s\'}\"}}";

			String NEW_URL_PATH = URL_PATH + "/" + devid;

			long currTime = new Date().getTime();
			Log.d("cdate", "" + currTime);

			Intent batteryIntent = trackingService.registerReceiver(null,
					new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
			batterylevel = batteryIntent.getIntExtra("level", -1);
			
			System.out.println("raj battery level: "+batterylevel);

			if (isOnline()) {

				String jsonStr = String.format(paramFormatStr, latitude, longitude,
						currTime, batterylevel, accval);

				try {
					httpclient = new DefaultHttpClient();
					httpost = new HttpPut(NEW_URL_PATH);

					JSONObject holder = new JSONObject();

					httpost.setHeader("Device", jsonStr);
					httpost.setHeader("Content-type", "application/json");

					response = httpclient.execute(httpost);

					if (response != null) {
						responseCode = response.getStatusLine().getStatusCode();

						System.out.println("raj the status code " + responseCode);

					}

					if (responseCode != 200) {
						
						if (dbh == null)
							dbh = new DatabaseHelper();
						insertDB(devid, currTime);
					} 

				} catch (Exception e) {

					System.out.println("the status code 0");
			
					if (dbh == null)
						dbh = new DatabaseHelper();
					insertDB(devid, currTime);
				} finally {

					if (httpclient == null) {

						Log.d("client", "null");
					} else {
						try {

							if (httpost != null)
								httpost.abort();
							if (response != null)
								response.getEntity().getContent().close();
							Log.d("client", "" + httpclient + " " + httpost + " "
									+ response);
						} catch (IllegalStateException e) {
							// TODO Auto-generated catch block
							// e.printStackTrace();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							// e.printStackTrace();
						}
					}
				}

				if (dbh == null)
					dbh = new DatabaseHelper();
				offlineDataSend(NEW_URL_PATH, paramFormatStr, devid);
				// }
			} else {

				if (dbh == null)
					dbh = new DatabaseHelper();
				insertDB(devid, currTime);
			}			
			return responseCode;
		}
		@Override
        protected void onPostExecute(Integer result) {

			System.out.println("raj Sent Data to Server: "+result);
        }

        @Override
        protected void onPreExecute() {
        	if (dbh == null)
				dbh = new DatabaseHelper();//raj
        	dbh.deleteEntireDatabase();
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
        }
	}
	public String getDeviceID()
	{
		TelephonyManager mngr = (TelephonyManager)trackingService.getSystemService(trackingService.TELEPHONY_SERVICE); 
		 return mngr.getDeviceId();
	}
	private Boolean isOnline() {
		ConnectivityManager cm = (ConnectivityManager)trackingService.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo ni = cm.getActiveNetworkInfo();
		if (ni != null && ni.isConnected())
			return true;
		return false;
	}
	public void insertDB(String devid, long currTime) {

		dbh.insertIntoDatabase(devid, devid, String.valueOf(latitude),
				String.valueOf(longitude), String.valueOf(currTime),
				String.valueOf(batterylevel), String.valueOf(accval));

		Log.d("inserted", "inserted");
	}
	public void offlineDataSend(String NEW_URL_PATH, String paramFormatStr,
			String devid) {

		if (!pendingService) {
			new SendData(NEW_URL_PATH, paramFormatStr).execute();
		}
	}
	class SendData extends AsyncTask<String, Void, String> {
		String new_url_path;
		String parameter;

		public SendData(String nEW_URL_PATH, String param) {
			// TODO Auto-generated constructor stub
			new_url_path = nEW_URL_PATH;
			parameter = param;
		}

		@Override
		protected String doInBackground(String... params) {
			// TODO Auto-generated method stub
			try {

				cursor = dbh.display();
				System.out.println("raj cursor count: "+cursor.getCount());
				if (cursor.getCount() > 0) {

					while (cursor.moveToNext()) {

						pendingService = true;

						String l1 = cursor.getString(cursor
								.getColumnIndex(DatabaseHelper.latitude));
						String l2 = cursor.getString(cursor
								.getColumnIndex(DatabaseHelper.longitude));
						String ac = cursor.getString(cursor
								.getColumnIndex("Accuracy"));

						String param = String
								.format(parameter,
										cursor.getString(cursor
												.getColumnIndex(DatabaseHelper.latitude)),
										cursor.getString(cursor
												.getColumnIndex(DatabaseHelper.longitude)),
										cursor.getString(cursor
												.getColumnIndex(DatabaseHelper.timeStamp)),
										cursor.getString(cursor
												.getColumnIndex(DatabaseHelper.batterylevel)),
										cursor.getString(cursor
												.getColumnIndex("Accuracy")));

						if (isOnline()) {
							makeRequest(
									new_url_path,
									param,
									cursor.getString(cursor
											.getColumnIndex(DatabaseHelper.timeStamp)),
									l1, l2, ac);
						} else {
							pendingService = false;
							break;
						}
					}
					pendingService = false;
				}
				cursor.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
			}
			return null;
		}
	}

	public int makeRequest(String path, String param, String timestamp,
			String l1, String l2, String ac) {

		HttpResponse response = null;
		DefaultHttpClient httpclient = null;
		HttpPut httpost = null;
		int responseCode = 0;

		try {

			Log.d("send offline data", "send offline data");
			httpclient = new DefaultHttpClient();
			httpost = new HttpPut(path);
			JSONObject holder = new JSONObject();
			httpost.setHeader("Device", param);
			httpost.setHeader("Content-type", "application/json");
			response = httpclient.execute(httpost);

			if (response != null)
				responseCode = response.getStatusLine().getStatusCode();
			System.out.println("the status code " + responseCode);

			if (responseCode != 200) {
				
			} else {

				dbh.deleteData(timestamp);
			}
		} catch (Exception e) {

			System.out.println("the status code 0");
			return 0;
		} finally {

			if (httpclient == null) {

				Log.d("client", "null");
			} else {
				try {

					if (httpost != null)
						httpost.abort();

					if (response != null)
						response.getEntity().getContent().close();

				} catch (IllegalStateException e) {
					// TODO Auto-generated catch block
					return 0;
				} catch (IOException e) {
					// TODO Auto-generated catch block
					return 0;
				}
			}
		}
		return responseCode;
	}

}
